
#pragma once

#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <vector>
#include <stack>

#define ALIGN_UP(n,align) (( (n) + ( (align)-1 ))&(~((align)-1)) )
#define ALIGN_DOWN(n,align) (( (n) - ( (align)-1 ))&(~((align)-1)) )

struct tCharInfo
{
	wchar_t ch;

	int slot;
	int page;

	float u1,v1;
	float u2,v2;
	
	int x_org,y_org;
	int x_inc,y_inc;
	int w,h;

	int ref_count;
};

class GLFontPage
{
public:

	int m_nCharWidth;
	int m_nCharHeight;

	int m_nPageWidth;
	int m_nPageHeight;

	std::stack<int> m_freeStack;
	GLuint m_texId;

	bool Create( int nCharWidth,int nCharHeight,int nPageWidth = 256,int nPageHeight = 256 );
	void Destroy();
	int GetFreeSlot();
	void FreeSlot( int slot );

};

class GLfont
{
public:
	GLfont();
	~GLfont();

	void Release();
	
	void SetMaxCharList( int nMaxCharList );
	void SetMaxCharPage( int nMaxCharPage );

	void Create( const LOGFONT* lf );
	void PresetExtent( int nCharWidth,int nCharHeight ){ m_nCharWidth = nCharWidth;m_nCharHeight = nCharHeight;} 
	
	void BeginFrame( int nFrameCount );
	void EndFrame();

	void AttachDC( HDC hDC ); 
	void SetTextColor( float r,float g,float b,float a ){m_textColor[0] = r;m_textColor[1]=g;m_textColor[2]=b;m_textColor[3] = a;};
	void SetGradTextColor( float r,float g,float b,float a ){m_textGradColor[0] = r;m_textGradColor[1]=g;m_textGradColor[2]=b;m_textGradColor[3] = a;};
	
	void PrintText( float x,float y,const wchar_t* str);
	void PrintGradText( int mode,float x,float y,const wchar_t* str);
	void PrintTextV( float x,float y,const wchar_t* fmt,...);
	void DrawChar( float x_offset,float y_offset,tCharInfo* info );
	void DrawGradChar( int mode,float x_offset,float y_offset,tCharInfo* info );

	std::vector<tCharInfo> m_charList;
	std::vector<GLFontPage*> m_pageList;

protected:

	float m_textColor[4];
	float m_textGradColor[4];
	int m_frameCount;
	int m_frameCountLast;

	void* m_charMem;
	HDC m_hdc;
	int m_nCharWidth;
	int m_nCharHeight;
	int m_nMaxCharList;
	int m_nMaxCharPage;
	tCharInfo* FindCharInfo( wchar_t ch );
	tCharInfo* CheckCharInfo( wchar_t ch );
	tCharInfo* InsertCharInfo( wchar_t ch );

};